package com.admgt.util.ftp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
public class FTPUtil { 
	
enum UploadStatus {
	REMOTE_FILE_NOT_UNIQUE,
	CREATE_DIRECTORY_FAIL,
	FILE_EXIST,
	REMOTE_EQUAL_LOCAL,
	REMOTE_BIGGER_LOCAL,
	UPLOAD_FROM_BREAK_SUCCESS,
	UPLOAD_FROM_BREAK_FAILED,
	DELETE_REMOTE_FAILED,
	UPLOAD_NEW_FILES_SUCCESS,
	UPLOAD_NEW_FILES_FAILED;
}

private FTPClient ftpClient = new FTPClient();  


public FTPUtil(){
	ftpClient.addProtocolCommandListener(new PrintCommandListener(
			new PrintWriter(System.out)));
	ftpClient.setControlEncoding("UTF-8");
     FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);   
     conf.setServerLanguageCode("zh"); 
     
}

public boolean connect(String hostname,int port,
		String username, String password)throws IOException{
	ftpClient.connect(hostname,port);
	if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
		if(ftpClient.login(username, password)){
			return true;
		}
	}
	disconnect();
	return false;
}

public void disconnect() throws IOException{
	if(ftpClient.isConnected()){
		ftpClient.disconnect();
	}
}
public boolean download(String remote,String local)throws IOException{
	ftpClient.enterLocalPassiveMode();//transfer by passive mode
	ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//transfer date by byte code
	boolean result;
	//get remote file size
	FTPFile[] files = ftpClient.listFiles(remote);
	if(files.length != 1){
		System.out.println("remote file is not unique!");
		return false;
	}
	long remoteSize = files[0].getSize();
	//start to down load files
	File localFile = new File(local);
	if(localFile.exists()){
		result = retryBrokenDownloads(localFile, remote, remoteSize);
	}else{
		result = downloadNewFile(localFile,remote);
		
	}
	return result;
}


private boolean downloadNewFile(File localFile, String remote) throws IOException{
	OutputStream out = new FileOutputStream(localFile);
	boolean result = ftpClient.retrieveFile(remote, out);
	out.close();
	return result;
}

private boolean retryBrokenDownloads(File localFile,String remote, 
		long remoteSize)throws IOException {
	OutputStream out = new FileOutputStream(localFile,true);
	long localSize = localFile.length();
	System.out.println("Local file size is:"+localSize);
	if(localSize >= remoteSize){
		System.out.println("Local file size is " +
				"equal or bigger than remote file size, download stopped.");
		return false;
	}
	ftpClient.setRestartOffset(localSize);
	boolean result = ftpClient.retrieveFile(remote, out);
	out.close();
	return result;
}

public UploadStatus upload(String local,String remote)throws IOException{
	ftpClient.enterLocalPassiveMode();//transfer by passive mode
	ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//transfer date by byte code
	UploadStatus result =null;
	//get remote file size
	FTPFile[] files = ftpClient.listFiles(remote);
	FTPFile[] files2 = ftpClient.listFiles("/");
	for(FTPFile f : files2){
		//System.out.println(":"+f.getRawListing());
		System.out.println(":"+f.toFormattedString());
	}
	//start to upload files
	File localFile =  new File(local);
	if(files.length == 1){
		long remoteSize = files[0].getSize();
		result = retryBrokenUploads(localFile, remote, remoteSize);
	}else{
		result = uploadNewFile(localFile,remote);
	}
	return result;
}

private UploadStatus uploadNewFile(File localFile, String remote) 
			throws IOException{
	InputStream in = new FileInputStream(localFile);
	UploadStatus result = null;
	if(ftpClient.storeFile(remote, in)){
		result = UploadStatus.UPLOAD_NEW_FILES_SUCCESS;
	}else{
		result = UploadStatus.UPLOAD_NEW_FILES_FAILED;
	}
	in.close();
	return result;
}

private UploadStatus retryBrokenUploads(File localFile, String remote,
		long remoteSize) throws IOException{
	UploadStatus result =null;  
	long localSize = localFile.length();
	System.out.println("Local file size is:"+localSize);
	if(remoteSize == localSize ){
		System.out.println("Remote file size is " +
				"equal local file size, download stopped.");
		return UploadStatus.REMOTE_EQUAL_LOCAL;
	}else if(remoteSize > localSize){
		System.out.println("Remote file size is " +
		"bigger than local file size, download stopped.");
		return UploadStatus.REMOTE_BIGGER_LOCAL;
	}
	InputStream in = new FileInputStream(localFile);
	if(in.skip(remoteSize) == remoteSize){
		ftpClient.setRestartOffset(remoteSize);
		if(ftpClient.storeFile(remote, in)){
			result =  UploadStatus.UPLOAD_FROM_BREAK_SUCCESS;
		}else{
			result =  UploadStatus.UPLOAD_FROM_BREAK_FAILED;
		}
	}
	in.close();
	return result;
}

public static void main(String[] args){
	FTPUtil ftp = new FTPUtil();
	try{
		//download files
		/*ftp.connect("10.225.106.40", 21, "myusername", "12345678");
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 
		Long start = System.currentTimeMillis();
		System.out.println("Start="+format.format(new Date(start)));
		ftp.download("dataRemote.txt", "C:/守望幸福.txt");
		
		Long end = System.currentTimeMillis();
		System.out.println("end="+format.format(new Date(end)));
		ftp.disconnect();*/
		
		//upload files
		ftp.connect("192.168.1.103", 21, "myusername", "12345678");
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 
		Long start = System.currentTimeMillis();
		System.out.println("Start="+format.format(new Date(start)));
		System.out.println(ftp.upload("C:\\北盟外语(www.bmwy.net)-阿甘正传.rmvb", "阿甘正传.rmvb"));
	
		Long end = System.currentTimeMillis();
		System.out.println("end="+format.format(new Date(end)));
		ftp.disconnect();
	}catch(Exception e){
		e.printStackTrace();
	}
}
} 